Skip to content

feat(packaging): add BlockPackageDef for hard-macro builds#167

Merged
lanserge merged 3 commits intomainfrom
feat/block-package
May 8, 2026
Merged

feat(packaging): add BlockPackageDef for hard-macro builds#167
lanserge merged 3 commits intomainfrom
feat/block-package

Conversation

@lanserge
Copy link
Copy Markdown
Contributor

Summary

Adds a parameterized package type used when chipflow.toml declares package = "block". Structurally a sibling of BareDiePackageDef — pins on four sides addressed by (Side, index) — but for hard-macro targets rather than packaged chips.

Differences vs chip packages

  • No bringup pins. Blocks take power via straps from the parent and route clocks/resets through regular pins. allocate_pins() skips the chip-package bringup step (the _allocate_bringup call that reserves clock/reset/power/JTAG slots at fixed positions).
  • Parameterized per project. width/height aren't fixed values in PACKAGE_DEFINITIONS — they come from a new [chipflow.silicon.block] table. The resolver in lock_pins() constructs a BlockPackageDef instance from config when package = "block".

chipflow.toml shape

[chipflow.silicon]
process = "ihp_sg13g2"
package = "block"

[chipflow.silicon.block]
width  = 50    # pin slots on N and S edges
height = 80    # pin slots on W and E edges

width and height are pin-slot counts, same units as QuadPackageDef.width/.heightnot microns. Translation to physical dimensions happens at the backend using the process's pin pitch.

What stays the same

  • Bundle.zip / manifest.json transport — no change.
  • Lockfile shape — BlockPackageDef is added to the PackageDef discriminated union; lockfile serialization works unchanged.
  • chipflow-api / chipflow-backend wire format — unchanged.

What's left for the backend

Backend grows a "block mode" code path: detect package_type == "BlockPackageDef" from the lockfile, run the ORFS macro flow (different floorplan + PnR strategy from chip flow), output LEF / Liberty / GDS / Verilog stub. None of that is in this PR.

Test plan

  • pytest --ignore=tests/test_cli_integration.py — 69 passed, 10 skipped.
  • ruff check chipflow/ tests/ clean.
  • New tests/test_block_package.py covers: perimeter slot count, no bringup reservation, abstract bringup property raises (so accidental calls fail loud), pydantic round-trip.
  • End-to-end against staging once the chipflow-backend macro flow is in place.

Related

This PR is independent of #163 — they touch disjoint files.

Adds a parameterized package type used when chipflow.toml declares
`package = "block"`. Structurally a sibling of BareDiePackageDef — pins
on four sides addressed by (Side, index) — but for hard-macro targets
rather than packaged chips.

Differences vs chip packages:
- No I/O pad ring, no JTAG, no fixed clock/reset/power slots. Blocks
  take power via straps from the parent and route clocks/resets through
  regular pins. allocate_pins() skips the bringup-pins step entirely.
- width/height are user-defined per project rather than pulled from a
  fixed PACKAGE_DEFINITIONS entry, sourced from a new
  [chipflow.silicon.block] table:

    [chipflow.silicon]
    process = "ihp_sg13g2"
    package = "block"

    [chipflow.silicon.block]
    width  = 50
    height = 80

  width/height are pin-slot counts, same units as QuadPackageDef. The
  backend translates to physical microns using the process's pin pitch.

The lockfile flows through the existing bundle.zip pipeline unchanged —
package_type discriminator routes deserialization, and the `_file`-keyed
manifest contract on the receiving side already covers everything.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 30, 2026

Tests Skipped Failures Errors Time
90 10 💤 0 ❌ 0 🔥 36.300s ⏱️

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 30, 2026

PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-05-08 07:49 UTC

lanserge and others added 2 commits May 7, 2026 16:56
Match QuadPackageDef so the chipflow-backend can use a single
packaging.map convention (W→S→E→N counter-clockwise) to translate
pin indices to physical (side, slot) locations. The earlier
(_Side, idx) tuple form would serialize as [side, idx] in the
lockfile, which the backend's pad loader collapses to the side
component alone — making every N-edge pin indistinguishable.
A block macro still needs real clock and reset boundary pins —
the parent design drives them through ordinary block pins, so
they must appear in the lockfile under `_core.bringup_pins`.
The previous BlockPackageDef.allocate_pins skipped bringup
allocation wholesale, leaving the macro with no clk/rst_n
entries.

Make BringupPins minimally constructible: core_power defaults
to [], core_heartbeat to None. Base _allocate_bringup walks an
empty power list and skips heartbeat when the pin is None, so
targets without a chip-style debug ring drop those entries
naturally. BlockPackageDef.bringup_pins now returns
BringupPins(core_clock=1, core_reset=2) and the rest of the
flow (model_post_init / allocate_pins) reuses the base path —
no overrides, no special case in wire-up.

Lockfile output for a block carries the same _core shape as a
chip, just containing only clk and rst_n.
@lanserge lanserge merged commit 42fb2d0 into main May 8, 2026
6 checks passed
@lanserge lanserge deleted the feat/block-package branch May 8, 2026 07:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant